package com.ujson.base.common.dto;

import com.ujson.base.common.enums.ErrorCode;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.util.Assert;

@Data
@NoArgsConstructor
public class Res<T> {
    private int code;
    private String msg;
    private T data;

    private Res(ErrorCode errorCode) {
        this(errorCode, null, null);
    }
    private Res(ErrorCode errorCode, T data) {
        this(errorCode, null, data);
    }
    private Res(ErrorCode errorCode, String msg, T data) {
        this.code = errorCode.getCode();
        this.msg = msg;
        if (StringUtils.isBlank(msg)) {
            this.msg = errorCode.getMsg();
        }
        this.data = data;
    }
    private Res(ErrorCode errorCode, String msg) {
        this(errorCode, msg, null);
    }

    public static <T> Res<T> success() {
        return new Res<>(ErrorCode.SUCCESS);
    }
    public static <T> Res<T> success(T data) {
        return new Res<>(ErrorCode.SUCCESS, data);
    }
    public static <T> Res<T> success(ErrorCode code, T data) {
        return new Res<>(code, data);
    }
    public static <T> Res<T> success(ErrorCode code, String msg) {
        return new Res<>(code, msg);
    }
    public static <T> Res<T> success(ErrorCode code, String msg, T data) {
        return new Res<>(code, msg, data);
    }

    public static <T> Res<T> fail() {
        return new Res<>(ErrorCode.FAIL);
    }
    public static Res<Object> fail(Throwable ex) {
        return new Res<>(ErrorCode.FAIL, ex.getMessage(), null);
    }
    public static <T> Res<T> fail(T data) {
        return new Res<>(ErrorCode.FAIL, data);
    }
    public static <T> Res<T> fail(ErrorCode code, T data) {
        failCodeCheck(code);
        return new Res<>(code, data);
    }
    public static <T> Res<T> fail(ErrorCode code) {
        return fail(code, null, null);
    }
    public static <T> Res<T> fail(ErrorCode code, String msg) {
        return fail(code, msg, null);
    }
    public static <T> Res<T> fail(ErrorCode code, String msg, T data) {
        failCodeCheck(code);
        return new Res<>(code, msg, data);
    }

    private static void failCodeCheck(ErrorCode code) {
        Assert.isTrue(code.getCode() < ErrorCode.SUCCESS.getCode(), "fail error code must less than 200000.");
    }


}
